

/**
 * A privacy item acts a rule that when matched defines if a packet should be blocked or not.
 *
 * Privacy Items can handle different kind of blocking communications based on JID, group,
 * subscription type or globally by:<ul>
 * <li>Allowing or blocking messages.
 * <li>Allowing or blocking inbound presence notifications.
 * <li>Allowing or blocking outbound presence notifications.
 * <li>Allowing or blocking IQ stanzas.
 * <li>Allowing or blocking all communications.
 * </ul>
 * @author Francisco Vives
 */
class PrivacyItem {
public:
	/**
     * Type defines if the rule is based on JIDs, roster groups or presence subscription types.
     */
    typedef enum {
		/**
		 * undefined
		 */
		undefined,

        /**
         * JID being analyzed should belong to a roster group of the list's owner.
         */
        group,
        /**
         * JID being analyzed should have a resource match, domain match or bare JID match.
         */
        jid,
        /**
         * JID being analyzed should belong to a contact present in the owner's roster with
         * the specified subscription status.
         */
        subscription
    } Type;
	class PrivacyRule {
	public:
        /**
     	 * If the type is "subscription", then the 'value' attribute MUST be one of "both",
     	 * "to", "from", or "none"
     	 */
     	static std::string SUBSCRIPTION_BOTH;
     	static std::string SUBSCRIPTION_TO;
     	static std::string SUBSCRIPTION_FROM;
     	static std::string SUBSCRIPTION_NONE;
		
        /**
         * Returns the type hold the kind of communication it will allow or block.
         * It MUST be filled with one of these values: jid, group or subscription.
         *
         * @return the type of communication it represent.
         */
        Type getType() { return type; };
		
        /**
         * Returns the element identifier to apply the action.
         *
         * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
         * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
         * in the user's roster.
         * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
         * "from", or "none".
         *
         * @return the identifier to apply the action.
         */
		std::string getValue() { return value; };
		
	protected:
		/**
         * Returns the type constant associated with the String value.
         */
        static PrivacyRule * fromString(std::string & value);
		         
		/**
         * Sets the element identifier to apply the action.
         *
         * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
         * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
         * in the user's roster.
         * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
         * "from", or "none".
         *
         * @param value is the identifier to apply the action.
         */
        void setValue(std::string & value);
		/**
         * Returns if the receiver represents a subscription rule.
         *
         * @return if the receiver represents a subscription rule.
         */
        bool isSubscription () { return type == subscription; };
	private:
		/**
         * Sets the action associated with the item, it can allow or deny the communication.
         *
         * @param type indicates if the receiver allows or denies the communication.
         */
        void setType(Type type) { this->type = type};
	
        /**
         * Sets the element identifier to apply the action.
         *
         * The 'value' attribute MUST be one of "both", "to", "from", or "none".
         *
         * @param value is the identifier to apply the action.
         */
        void setSuscriptionValue(std::string & value);

		/**
    	  * Type defines if the rule is based on JIDs, roster groups or presence subscription types.
    	  * Available values are: [jid|group|subscription]
    	  */
    	Type type;
		
		/**
          * The value hold the element identifier to apply the action.
          * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
          * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
          * in the user's roster.
          * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
          * "from", or "none".
          */
		std::string value;


	} ;

    /**
     * Creates a new privacy item.
     *
     * @param type the type.
     */
    PrivacyItem(std::string & type, bool allow, int order) : type(type), allow(allow), order(order) {};
	
    /**
     * Returns the action associated with the item, it MUST be filled and will allow or deny
     * the communication.
     *
     * @return the allow communication status.
     */
    bool isAllow() {
		return allow;
	}

    /**
     * Returns whether the receiver allow or deny incoming IQ stanzas or not.
     *
     * @return the iq filtering status.
     */
    bool isFilterIQ() {
		return filterIQ;
	}


    /**
     * Sets whether the receiver allows or denies incoming IQ stanzas or not.
     *
     * @param filterIQ indicates if the receiver allows or denies incoming IQ stanzas.
     */
    void setFilterIQ(bool filterIQ) {
		this->filterIQ = filterIQ;
	}

    /**
     * Returns whether the receiver allows or denies incoming messages or not.
     *
     * @return the message filtering status.
     */
    bool isFilterMessage() {
		return filterMessage;
	}

    /**
     * Sets wheather the receiver allows or denies incoming messages or not.
     *
     * @param filterMessage indicates if the receiver allows or denies incoming messages or not.
     */
    void setFilterMessage(bool filterMessage) {
		this->filterMessage = filterMessage;
	}
	
    /**
     * Returns whether the receiver allows or denies incoming presence or not.
     *
     * @return the iq filtering incoming presence status.
     */
    bool isFilterPresence_in() {
		return filterPresence_in;
	}

    /**
     * Sets whether the receiver allows or denies incoming presence or not.
     *
     * @param filterPresence_in indicates if the receiver allows or denies filtering incoming presence.
     */
    void setFilterPresence_in(bool filterPresence_in) {
		this->filterPresence_in = filterPresence_in;
	}

    /**
     * Returns whether the receiver allows or denies incoming presence or not.
     *
     * @return the iq filtering incoming presence status.
     */
    bool isFilterPresence_out() {
		return filterPresence_out;
	}
	
    /**
     * Sets whether the receiver allows or denies outgoing presence or not.
     *
     * @param filterPresence_out indicates if the receiver allows or denies filtering outgoing presence
     */
    void setFilterPresence_out(bool filterPresence_out) {
		this->filterPresence_out = filterPresence_out;
	}

    /**
     * Returns the order where the receiver is processed. List items are processed in
     * ascending order.
     *
     * The order MUST be filled and its value MUST be a non-negative integer
     * that is unique among all items in the list.
     *
     * @return the order number.
     */
    int getOrder() {
		return order;
	}

    /**
     * Sets the element identifier to apply the action.
     *
     * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
     * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
     * in the user's roster.
     * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
     * "from", or "none".
     *
     * @param value is the identifier to apply the action.
     */
    void setValue(std::string & value) {
		/* why getRule rather than rule directly */
    	if (!rule == NULL && !value.empty()) {
    		rule->setValue(value);
    	}
	}


	
    /**
     * Returns the type hold the kind of communication it will allow or block.
     * It MUST be filled with one of these values: jid, group or subscription.
     *
     * @return the type of communication it represent.
     */
    Type getType() {
		return rule == NULL ? undefined : rule->getType();
	}
	
    /**
     * Returns the element identifier to apply the action.
     *
     * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
     * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
     * in the user's roster.
     * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
     * "from", or "none".
     *
     * @return the identifier to apply the action.
     */
	std::string getValue() {
		return rule == NULL ? "" : rule->getValue();
	}
	
    /**
     * Returns whether the receiver allows or denies every kind of communication.
     *
     * When filterIQ, filterMessage, filterPresence_in and filterPresence_out are not set
     * the receiver will block all communications.
     *
     * @return the all communications status.
     */
    bool isFilterEverything() {
		return !(filterIQ || filterMessage || filterPresence_in
				|| filterPresence_out);
	}

	/**
	 * Answer an xml representation of the receiver according to the RFC 3921.
	 *
	 * @return the text xml representation.
     */
	std::string toXML();

private: 	
    /**
     * Sets the action associated with the item, it can allow or deny the communication.
     *
     * @param allow indicates if the receiver allow or deny the communication.
     */
    void setAllow(bool allow) {
		this->allow = allow;
	}

    /**
     * Sets the order where the receiver is processed.
     *
     * The order MUST be filled and its value MUST be a non-negative integer
     * that is unique among all items in the list.
     *
     * @param order indicates the order in the list.
     */
    void setOrder(int order) {
		this->order = order;
	}
	
	PrivacyRule * getRule() {
		return rule;
	}

	void setRule(PrivacyRule * rule) {
		this->rule = rule;
	}

	/** allow is the action associated with the item, it can allow or deny the communication. */
	bool allow;
	/** order is a non-negative integer that is unique among all items in the list. */
    int order;
    /** rule hold the kind of communication ([jid|group|subscription]) it will allow or block and
     * identifier to apply the action.
     * If the type is "jid", then the 'value' attribute MUST contain a valid Jabber ID.
     * If the type is "group", then the 'value' attribute SHOULD contain the name of a group
     * in the user's roster.
     * If the type is "subscription", then the 'value' attribute MUST be one of "both", "to",
     * "from", or "none". */
    PrivacyRule * rule;

    /** blocks incoming IQ stanzas. */
    bool filterIQ ;
    /** filterMessage blocks incoming message stanzas. */
    bool filterMessage ;
    /** blocks incoming presence notifications. */
    bool filterPresence_in ;
    /** blocks outgoing presence notifications. */
    bool filterPresence_out ;

};
